#ifndef EMPTYOBJECT_H_INCLUDED
#define EMPTYOBJECT_H_INCLUDED

#include <Math/Vector.hpp>
#include <General/cvMemory.h>
#include "BaseObject.h"

namespace cvObjects
{
	/**
	 *	The EmptyObject.
	 *	Object that can be placed in game world.
	 */
	class EmptyObject : public BaseObject
	{
		public:
			/** Construct a EmptyObject */
			static EmptyObject * create();

			/// Creates a duplicate of the object.
			virtual EmptyObject * copy( cvMath::bitfield_t flags );

			/** Destructor & destroy */
			virtual void destroy();
			static void purgeMemoryPool();

			/** Type of the object */
			virtual int objectType() const;

			/** Object parenting */
			virtual void setRelativity( cvMath::bitfield_t flags );

			/// Setters
			void position( const cvMath::Vec2f & p );
			void rotate( float angle );
			void move( float forwrd, float sidewrd = 0.0f );
			void turn( float delta );
			void translate( const cvMath::Vec2f & p );
			/// Getters
			const cvMath::Vec2f & position();
			float angle();
			const cvMath::Vec2f & localPosition() const;
			float localAngle() const;


		protected:
			EmptyObject();

			virtual void updater();

		private:
			/** Memory allocation */
			void * operator new( size_t );
			void operator delete( void* );
			void * operator new[]( size_t dummy )	{ throw; }
			void operator delete[]( void * dummy )	{ throw; }
			static cvPool pool;

			// relativity modes.
			typedef void ( EmptyObject::*relativity_fn )();
			void xyrot_update();		// Both rotation and position are relative to parent.
			void xy_update();			// Only position
			void rot_update();			// Only rotation
			void x_update();
			void y_update();
			//void xrot_update();
			//void yrot_update();
			relativity_fn fn_updater;

			/*	position(), rotate(), move(), turn() and translate() behaviour varies by the relativity setting. */

			// spawn of position()
			typedef void ( EmptyObject::*position_fn )( const cvMath::Vec2f& );
			void position_glb( const cvMath::Vec2f& );
			void position_local( const cvMath::Vec2f& );
			void position_localx( const cvMath::Vec2f& );
			void position_localy( const cvMath::Vec2f& );
			position_fn fn_position;

			// spawn of rotate()
			typedef void ( EmptyObject::*rotate_fn )( float );
			void rotate_glb( float );
			void rotate_local( float );
			rotate_fn fn_rotate;

			// spawn of move()
			typedef void ( EmptyObject::*move_fn )( float, float );
			void move_glb( float, float );
			void move_local( float, float );
			void move_localx( float, float );
			void move_localy( float, float );
			move_fn fn_move;

			// spawn of turn()
			typedef void ( EmptyObject::*turn_fn )( float );
			void turn_glb( float );
			void turn_local( float );
			rotate_fn fn_turn;

			// spawn of translate()
			typedef void ( EmptyObject::*translate_fn )( const cvMath::Vec2f& );
			void translate_glb( const cvMath::Vec2f& );
			void translate_local( const cvMath::Vec2f& );
			void translate_localx( const cvMath::Vec2f& );
			void translate_localy( const cvMath::Vec2f& );
			translate_fn fn_translate;

			// local position & rotation
			cvMath::Vec2f m_localpos;
			float m_localrot;

			/// the absolute position & rotation
			cvMath::Vec2f m_position;
			float m_rotation;
	};
};
#endif // EMPTYOBJECT_H_INCLUDED
